#include "CCmdMainctrlInitData.h"
#include "../mainctrl.h"
#include "../cmd/cmdselectdatafromdbsvr.h"
#include "CCmdInitOnlineData.h"
#include "commmsg.h"

CT_REGISTER_ASYNCCMD(ID_MAIN_INNER_MAINCTRL_INIT_DATA , CCmdMainctrlInitData);

int CCmdMainctrlInitData::Do(void* pData)
{
    if (pData != NULL)
    {
        CT_WARNING(("inner cmd CCmdMainctrlInitData get data"));
        return Done(RET_OK);
    }

    if (pstMainCtrl == NULL)
    {
        CT_ERROR(("mainctrl point is null"));
        return Done(RET_SYSTEM_FAIL);
    }

    if (pstMainCtrl->m_bDataIsInited)
    {
        CT_ERROR(("mainctrl data is inited"));
        return Done(RET_SYSTEM_FAIL);
    }

    return SendReq();
}

int CCmdMainctrlInitData::SendReq()
{
    int iRet = 0;

    //创建命令
    CCmdSelectDataFromDBSvr* pstCmd = (CCmdSelectDataFromDBSvr*)CT_CMDFACTORY->CreateCmd(ID_MAINDB_SELECTDATA);
    if (!pstCmd)
    {
        CT_WARNING(("create cmd error"));
        return Done(RET_SYSTEM_FAIL);
    }
    pstCmd->pstMainCtrl = pstMainCtrl;

    //初始化
    switch(_iNowStat)
    {
    case INIT_STAT_FLUSH_DATA:      //先要通知dbsvr将数据全部刷入数据库，否则在做全cache数据拉取的时候会出现数据不一致
        {
            pstCmd->stReq.m_ucCheckUpdateMgr = 0;
            pstCmd->stReq.m_stKey.m_chDataType = DT_FLUSH_DBSVR_DATA;
        }
        break;
    case INIT_STAT_ZONE_COUNT:
        {
            pstCmd->stReq.m_ucCheckUpdateMgr = 0;
            pstCmd->stReq.m_stKey.m_chDataType = DT_ZONE_COUNT;
            pstCmd->stReq.m_stKey.m_u64ID = 0;
        }
        break;
    case INIT_STAT_ZONE_DATA:
        {
            pstCmd->stReq.m_ucCheckUpdateMgr = 0;
            pstCmd->stReq.m_stKey.m_chDataType = DT_ZONE_DATA;
            pstCmd->stReq.m_stKey.m_u64ID = pstMainCtrl->ZoneID();
        }
        break;
    case INIT_STAT_MAX_PLAYER_ID:
        {
            pstCmd->stReq.m_ucCheckUpdateMgr = 0;
            pstCmd->stReq.m_stKey.m_chDataType = DT_MAX_PLAYER_GID;
        }
        break;
    case INIT_STAT_SNS_COMM_INFO_COUNT:
        {
            pstCmd->stReq.m_ucCheckUpdateMgr = 0;
            pstCmd->stReq.m_stKey.m_chDataType = DT_PLAYER_SNS_COMM_INFO_COUNT;
        }
        break;
    case INIT_STAT_SNS_COMM_INFO:
        {
            pstCmd->stReq.m_ucCheckUpdateMgr = 0;
            pstCmd->stReq.m_stKey.m_chDataType = DT_PLAYER_SNS_COMM_INFO;
        }
        break;
    case INIT_STAT_ARENA_RANK_COUNT:
        {
            pstCmd->stReq.m_ucCheckUpdateMgr = 0;
            pstCmd->stReq.m_stKey.m_chDataType = DT_ARENA_RANK_COUNT;
        }
        break;
    case INIT_STAT_ARENA_RANK:      //必须在INIT_STAT_SNS_COMM_INFO后面，见CArenaMgr::AddData函数
        {
            pstCmd->stReq.m_ucCheckUpdateMgr = 0;
            pstCmd->stReq.m_stKey.m_chDataType = DT_ARENA_RANK;
        }
        break;
    case INIT_STAT_CLAN_DATA_COUNT:
        {
            pstCmd->stReq.m_ucCheckUpdateMgr = 0;
            pstCmd->stReq.m_stKey.m_chDataType = DT_CLAN_DATA_COUNT;
        }
        break;
    case INIT_STAT_CLAN_DATA:
        {
            pstCmd->stReq.m_ucCheckUpdateMgr = 0;
            pstCmd->stReq.m_stKey.m_chDataType = DT_CLAN_DATA;
        }
        break;
    case INIT_STAT_ONLINE_DATA:
        {
            pstCmd->Done(RET_OK);

            CCmdInitOnlineData* pstNewCmd = (CCmdInitOnlineData*)CT_CMDFACTORY->CreateCmd(ID_MAIN_INNER_INIT_ONLINE_USER);
            if (!pstCmd)
            {
                CT_WARNING(("create cmd error"));
                return Done(RET_SYSTEM_FAIL);
            }
            pstNewCmd->pstMainCtrl = pstMainCtrl;

            RegisterChild(pstNewCmd);
            return pstNewCmd->Do(NULL);
        }
        break;
    case INIT_STAT_GET_DATA_FROM_DETAIL_EX1:
        {
            if (_iDataIndex < 0)
            {
                _iDataIndex = 0;
            }

            if (_iDataIndex >= pstMainCtrl->m_auiAllRegisterGID.Size())
            {
                _iNowStat++;
                _iDataIndex = -1;
                pstCmd->Done(RET_OK);
                return SendReq();
            }

            pstCmd->stReq.m_ucCheckUpdateMgr = 0;
            pstCmd->stReq.m_stKey.m_chDataType = DT_PLAYER_DETAIL_EX1_INFO;
            pstCmd->stReq.m_stKey.m_u64ID = pstMainCtrl->m_auiAllRegisterGID[_iDataIndex];
        }
        break;
    case INIT_STAT_GET_DATA_FROM_BASE_INFO:
        {
            if (_iDataIndex < 0)
            {
                _iDataIndex = 0;
            }

            if (_iDataIndex >= pstMainCtrl->m_auiAllRegisterGID.Size())
            {
                _iNowStat++;
                _iDataIndex = -1;
                pstCmd->Done(RET_OK);
                return SendReq();
            }

            pstCmd->stReq.m_ucCheckUpdateMgr = 0;
            pstCmd->stReq.m_stKey.m_chDataType = DT_PLAYER_BASE_INFO;
            pstCmd->stReq.m_stKey.m_u64ID = pstMainCtrl->m_auiAllRegisterGID[_iDataIndex];
        }
        break;
    case INIT_STAT_GET_DATA_FROM_SNS_DETAIL_INFO:
        {
#if 0
            //暂时不用获取sns信息
            _iNowStat++;
            _iDataIndex = -1;
            pstCmd->Done(RET_OK);
            return SendReq();
#endif

            if (_iDataIndex < 0)
            {
                _iDataIndex = 0;
            }

            if (_iDataIndex >= pstMainCtrl->m_auiAllRegisterGID.Size())
            {
                _iNowStat++;
                _iDataIndex = -1;
                pstCmd->Done(RET_OK);
                return SendReq();
            }

            pstCmd->stReq.m_ucCheckUpdateMgr = 0;
            pstCmd->stReq.m_stKey.m_chDataType = DT_PLAYER_SNS_DETAIL_INFO;
            pstCmd->stReq.m_stKey.m_u64ID = pstMainCtrl->m_auiAllRegisterGID[_iDataIndex];
        }
        break;
    default:
        {
            pstMainCtrl->m_bDataIsInited = true;
            pstCmd->Done(RET_OK);
        }
        return Done(RET_OK);
    }

    RegisterChild(pstCmd);
    iRet = pstCmd->Do(NULL);
    CT_INFO(("init stat %d", _iNowStat));
    return CheckRet(iRet);
}

int CCmdMainctrlInitData::CallBack(int iRet)
{
    if (iRet != 0 && _iNowStat != INIT_STAT_ZONE_DATA)
    {
        if (RET_SYS_CMD_TIMEOUT == iRet)
        {
            if (INIT_STAT_GET_DATA_FROM_DETAIL_EX1 == _iNowStat
                || INIT_STAT_GET_DATA_FROM_BASE_INFO == _iNowStat
                || INIT_STAT_GET_DATA_FROM_SNS_DETAIL_INFO == _iNowStat)
            {
                CT_WARNING(("init data: cmd time out %d", _iNowStat));
                SendReq();
                return RET_OK;
            }
        }

        CT_ERROR(("CCmdMainctrlInitData::CallBack() recv error %d, %d", iRet, _iNowStat));
        return Done(iRet);
    }

    switch(_iNowStat)
    {
    case INIT_STAT_FLUSH_DATA:
        {
            unsigned char ucIsEmpty = 0;
            CAnsSelectData& stAns = ((CCmdSelectDataFromDBSvr*)m_pstChild)->stAns;
            iRet = pstMainCtrl->DataDecode(ucIsEmpty, stAns.pszData, stAns.iDataLen);
            CHECK_RETURN(iRet);

            if (ucIsEmpty == 1)
            {
                CT_INFO(("START......stat flush data OK!"));
                _iNowStat++;
            }
            else
            {
                CT_INFO(("wait for flush data!"));
            }

            SendReq();
            return RET_OK;
        }
        break;
    case INIT_STAT_ZONE_COUNT:
        {
            if (!m_pstChild)
            {
                CT_ERROR((""));
                CheckRet(RET_SYS_ERROR);
            }

            _i64ZoneCount = 0;
            CAnsSelectData& stAns = ((CCmdSelectDataFromDBSvr*)m_pstChild)->stAns;
            iRet = pstMainCtrl->DataDecode(_i64ZoneCount, stAns.pszData, stAns.iDataLen);
            CHECK_RETURN(iRet);

            CT_TRACE(("get zone count %lld", _i64ZoneCount));
            CT_INFO(("START......get zone count OK!"));
            _iNowStat++;
            SendReq();
            return RET_OK;
        }
        break;
    case INIT_STAT_ZONE_DATA:
        {
            if (iRet != RET_OK)
            {
                if (RET_NO_RECORDER == iRet)
                {
                    //新开大区
                    CZoneData stZoneData;
                    stZoneData._uiZoneID = pstMainCtrl->ZoneID();
                    stZoneData._iZoneOpenTime = time(NULL);
                    stZoneData._iZoneRecorderCount = 1;
                    pstMainCtrl->m_stZoneOnlineData.SetZoneData(stZoneData);

                    //保存数据
                    CVarObjectKey stKey;
                    stKey.m_chDataType = DT_ZONE_DATA;
                    stKey.m_u64ID = stZoneData._uiZoneID;
                    pstMainCtrl->UpdateData(stKey, stZoneData, VOP_CREATE);
                }
                else
                {
                    CT_ERROR(("CCmdMainctrlInitData::CallBack() recv error %d", iRet));
                    return Done(iRet);
                }
            }
            else
            {
                //判断合服时间
                CZoneData& stZoneData = pstMainCtrl->m_stZoneOnlineData._stZoneData;
                if ((int)_i64ZoneCount > stZoneData._iZoneRecorderCount)
                {
                    stZoneData._iZoneRecorderCount = (int)_i64ZoneCount;
                    stZoneData._iZoneCombineTime = time(NULL);      //合服时间

                    //保存数据
                    CVarObjectKey stKey;
                    stKey.m_chDataType = DT_ZONE_DATA;
                    stKey.m_u64ID = stZoneData._uiZoneID;
                    pstMainCtrl->UpdateData(stKey, stZoneData, VOP_CREATE);
                }

                //修复数据
                if (stZoneData._iZoneRecorderCount > _i64ZoneCount)
                {
                    stZoneData._iZoneRecorderCount = (int)_i64ZoneCount;

                    //保存数据
                    CVarObjectKey stKey;
                    stKey.m_chDataType = DT_ZONE_DATA;
                    stKey.m_u64ID = stZoneData._uiZoneID;
                    pstMainCtrl->UpdateData(stKey, stZoneData, VOP_CREATE);
                }

                //初始化竞技场数据
                iRet = pstMainCtrl->m_stArenaMgr.InitData(stZoneData._stArenaZoneData);
                CHECK_RETURN(iRet);

                //初始化学院数据
                iRet = pstMainCtrl->m_stAcademyMgr.InitData(stZoneData._stAcaemyZoneData);
                CHECK_RETURN(iRet);

                //初始化学院杯数据
                iRet = pstMainCtrl->m_stAcaCupMgr.InitData(pstMainCtrl->m_stZoneOnlineData._stZoneData._stAcaCupZoneData);
                CHECK_RETURN(iRet);
            }

            CT_INFO(("START......stat zone data OK!"));
            _iNowStat++;
            SendReq();
            return RET_OK;
        }
        break;
    case INIT_STAT_MAX_PLAYER_ID:
        {
            CT_TRACE(("get max player id %d", pstMainCtrl->m_uiMaxGID));
            _iNowStat++;
            CT_INFO(("START......get max player id OK!"));
            SendReq();
            return RET_OK;
        }
        break;
    case INIT_STAT_SNS_COMM_INFO_COUNT:
        {
            if (!m_pstChild)
            {
                CT_ERROR((""));
                CheckRet(RET_SYS_ERROR);
            }

            _i64LeftSnsCommInfoCount = 0;
            CAnsSelectData& stAns = ((CCmdSelectDataFromDBSvr*)m_pstChild)->stAns;
            iRet = pstMainCtrl->DataDecode(_i64LeftSnsCommInfoCount, stAns.pszData, stAns.iDataLen);
            CHECK_RETURN(iRet);

            CT_TRACE(("get sns comm info count %lld", _i64LeftSnsCommInfoCount));
            CT_INFO(("START......get sns comm info count OK!"));
            _iNowStat++;
            if (_i64LeftSnsCommInfoCount == 0)
            {
                _iNowStat++;        //没有数据就跳过下个阶段
            }
            SendReq();
            return RET_OK;
        }
        break;
    case INIT_STAT_SNS_COMM_INFO:
        {
            if (!m_pstChild)
            {
                CT_ERROR((""));
                return RET_SYS_ERROR;
            }

            _i64LeftSnsCommInfoCount--;
            CT_TRACE(("left sns comm info count %lld", _i64LeftSnsCommInfoCount));
            if (_i64LeftSnsCommInfoCount > 0)
            {
                m_pstChild->m_bFreeSelf = false;
            }
            else
            {
                CT_INFO(("START......init sns comm info OK!"));
                _iNowStat++;
                SendReq();
            }

            return RET_OK;
        }
        break;
    case INIT_STAT_ARENA_RANK_COUNT:
        {
            if (!m_pstChild)
            {
                CT_ERROR((""));
                CheckRet(RET_SYS_ERROR);
            }

            _i64LeftArenaUserCount = 0;
            CAnsSelectData& stAns = ((CCmdSelectDataFromDBSvr*)m_pstChild)->stAns;
            iRet = pstMainCtrl->DataDecode(_i64LeftArenaUserCount, stAns.pszData, stAns.iDataLen);
            CHECK_RETURN(iRet);

            CT_TRACE(("get arena user count %lld", _i64LeftArenaUserCount));
            CT_INFO(("START......get arena rank count OK!"));
            _iNowStat++;
            if (_i64LeftArenaUserCount == 0)
            {
                _iNowStat++;        //没有数据就跳过下个阶段
            }
            SendReq();
            return RET_OK;
        }
        break;
    case INIT_STAT_ARENA_RANK:
        {
            if (!m_pstChild)
            {
                CT_ERROR((""));
                return RET_SYS_ERROR;
            }

            _i64LeftArenaUserCount--;
            CT_TRACE(("left arena user count %lld", _i64LeftArenaUserCount));
            if (_i64LeftArenaUserCount > 0)
            {
                m_pstChild->m_bFreeSelf = false;
            }
            else
            {
                CT_INFO(("START......init arena rank OK!"));
                _iNowStat++;
                SendReq();
            }

            return RET_OK;
        }
        break;
    case INIT_STAT_CLAN_DATA_COUNT:
        {
            if (!m_pstChild)
            {
                CT_ERROR((""));
                CheckRet(RET_SYS_ERROR);
            }

            _i64LeftClanDataCount = 0;
            CAnsSelectData& stAns = ((CCmdSelectDataFromDBSvr*)m_pstChild)->stAns;
            iRet = pstMainCtrl->DataDecode(_i64LeftClanDataCount, stAns.pszData, stAns.iDataLen);
            CHECK_RETURN(iRet);

            CT_TRACE(("get clan data count %lld", _i64LeftClanDataCount));
            CT_INFO(("START......get clan data count OK!"));
            _iNowStat++;
            if (_i64LeftClanDataCount == 0)
            {
                _iNowStat++;        //没有数据就跳过下个阶段
            }
            SendReq();
            return RET_OK;
        }
        break;
    case INIT_STAT_CLAN_DATA:
        {
            if (!m_pstChild)
            {
                CT_ERROR((""));
                return RET_SYS_ERROR;
            }

            _i64LeftClanDataCount--;
            CT_TRACE(("left clan data count %lld", _i64LeftClanDataCount));
            CT_INFO(("START......init clan data OK!"));
            if (_i64LeftClanDataCount > 0)
            {
                m_pstChild->m_bFreeSelf = false;
            }
            else
            {
                _iNowStat++;
                SendReq();
            }

            return RET_OK;
        }
        break;
    case INIT_STAT_ONLINE_DATA:
        {
            _iNowStat++;
            SendReq();

            return RET_OK;
        }
        break;
    case INIT_STAT_GET_DATA_FROM_DETAIL_EX1:
        {
            unsigned int uiGID = pstMainCtrl->m_auiAllRegisterGID[_iDataIndex];
            int iIndex = pstMainCtrl->m_stPlayerDetailEx1InfoHash.HashFind(uiGID);
            if (iIndex < 0)
            {
                CT_WARNING(("get detail ex1 data error , gid = %u", uiGID));
            }
            else
            {
                CPlayerDetailInfoEx1& stPlayerDetailEx1Info = pstMainCtrl->m_stPlayerDetailEx1InfoHash[iIndex];

                //初始化悬赏令任务
                pstMainCtrl->m_stTaskMgr.InitRewardTask(stPlayerDetailEx1Info._stRewardTask, uiGID);

                //初始化学院杯
                pstMainCtrl->m_stAcaCupMgr.InitFirstRoundRole(uiGID, stPlayerDetailEx1Info._stAcaCupUserData);
                pstMainCtrl->m_stAcaCupMgr.AddGuessHis(uiGID, stPlayerDetailEx1Info._stAcaCupUserData);
            
                //换出数据，避免hash满
                pstMainCtrl->m_stPlayerDetailEx1InfoHash.HashFreeByIndex(iIndex);
            }

            _iDataIndex++;
            SendReq();
            return RET_OK;
        }
        break;
    case INIT_STAT_GET_DATA_FROM_BASE_INFO:
        {
            unsigned int uiGID = pstMainCtrl->m_auiAllRegisterGID[_iDataIndex];
            int iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(uiGID);
            if (iIndex < 0)
            {
                //CT_WARNING(("get base info data error , gid = %u", uiGID));
            }
            else
            {
                CPlayerBaseInfo& stPlayerBaseInfo = pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];
                
                //更新排名数据（合服用，需一直保留该逻辑）
                CArenaRank stArenaRank;
                pstMainCtrl->m_stArenaMgr.GetRankInfo(uiGID, stArenaRank);
                CMainCtrl::m_pstMain->m_stAcademyMgr.ArenaChange(uiGID, stArenaRank.GetRank(),stPlayerBaseInfo._ucAcademy);

                //换出数据，避免hash满，也避免同个数据再次被执行
                pstMainCtrl->m_stPlayerBaseInfoHash.HashFreeByIndex(iIndex);
            }

            if (pstMainCtrl->m_bIsSysBusy)
            {
                return PushQueue(RET_OK);
            }

            _iDataIndex++;
            SendReq();
            return RET_OK;
        }
        break;
    case INIT_STAT_GET_DATA_FROM_SNS_DETAIL_INFO:
        {
            unsigned int uiGID = pstMainCtrl->m_auiAllRegisterGID[_iDataIndex];
            int iIndex = pstMainCtrl->m_stPlayerSnsDetailInfoHash.HashFind(uiGID);
            if (iIndex < 0)
            {
                CT_WARNING(("get sns detail info data error , gid = %u", uiGID));
            }
            else
            {
                int iNowTime = time(NULL);
                CPlayerSnsDetailInfo& stPlayerSnsDetailInfo = pstMainCtrl->m_stPlayerSnsDetailInfoHash[iIndex];
                
                //确保竞技场排名正确（合服用，需一直保留该逻辑）
                CArenaRank stArenaRank;
                if (pstMainCtrl->m_stArenaMgr.GetRankInfo(uiGID, stArenaRank) == 0)
                {
                    if (stArenaRank._iNowRank != stPlayerSnsDetailInfo._stCommInfo._iArenaRank)
                    {
                        stPlayerSnsDetailInfo._stCommInfo._iArenaRank = stArenaRank._iNowRank;

                        //保存数据
                        CVarObjectKey stKey;
                        stKey.m_chDataType = DT_PLAYER_SNS_DETAIL_INFO;
                        stKey.m_u64ID = uiGID;
                        pstMainCtrl->UpdateData(stKey, stPlayerSnsDetailInfo, VOP_UPDATE);
                    }
                }

                //更新学院排名（合服用，需一直保留该逻辑）
                pstMainCtrl->m_stAcademyMgr.SilverChange(uiGID, 
                        stPlayerSnsDetailInfo._stMyInfo._stPlayerStatic._stTodayGetSilver.Get(iNowTime), 
                        stPlayerSnsDetailInfo._stCommInfo._ucAcademy);

                pstMainCtrl->m_stAcademyMgr.ConChange(uiGID, 
                    stPlayerSnsDetailInfo._stMyInfo._stPlayerStatic._stTodayContribution.Get(iNowTime), 
                    stPlayerSnsDetailInfo._stCommInfo._ucAcademy);

                pstMainCtrl->m_stAcademyMgr.RepChange(uiGID, 
                    stPlayerSnsDetailInfo._stMyInfo._stPlayerStatic._stTodayGetReputation.Get(iNowTime), 
                    stPlayerSnsDetailInfo._stCommInfo._ucAcademy);

                //换出数据，避免hash满，也避免同个数据再次被执行
                pstMainCtrl->m_stPlayerSnsDetailInfoHash.HashFreeByIndex(iIndex);
            }

            if (pstMainCtrl->m_bIsSysBusy)
            {
                return PushQueue(RET_OK);
            }

            _iDataIndex++;
            SendReq();
            return RET_OK;
        }
        break;
    default:
        SendReq();
        return RET_OK;
    }

    return Done(iRet);
}

